//creates text object
sCanvas.fn.text = function() {
	if (arguments.length !== 2 && arguments.length !== 3) {
		throw new Error("Wrong arguments was passed to text().");
	}
	
	try {
		var attrs,
			obj = new CanvasText(this, arguments[0]);
		
		if (arguments.length === 2) {
			attrs = arguments[1];
		} else {
			attrs = {
				x: arguments[1],
				y: arguments[2]
			};
		}

		obj.attr(attrs);

		this.register(obj);
		this.autorepaint();
		
		return obj;
	} catch (err) {
		throw err;
	}
};



var CanvasText = function(sc, text) {
	this.init(sc);
	this.addSupportedAttr(["fontFamily", "fontSize", "fontWeight", "fontStyle", "align", "baseline", "direction"]);
	this.addAnimatableAttr(["fontSize"]);
	sCanvas.extend(this.attrHandlers, {
		fontFamily: this.setFont,
		fontSize: this.setFont,
		fontWeight: this.setFont,
		fontStyle: this.setFont
	});
	this.initAttrs();

	try {
		this.val(text);
	} catch (err) {
		throw err;
	}

	return this;
};

CanvasText.prototype = new sCanvasObject();

sCanvas.fn.extend(true, {
	defaultAttrs: {
		fontFamily: "sans-serif",
		fontSize: 10,
		align: "left",
		baseline: "alphabetic",
		direction: "inherit"
	}
});

CanvasText.prototype.createFillPath = function(cx) {};

CanvasText.prototype.createStrokePath = function(cx) {};

CanvasText.prototype.createPointInPath = function(cx) {
	var metrics = this.metrics();
	var top = -metrics[this.attrs.baseline];
	var left = this.attrs.align === "left" ? 0
			: (this.attrs.align === "right" ? -metrics.width : (-metrics.width / 2));
	
	cx.save();
	cx.translate(this.attrs.x, this.attrs.y);
	cx.rotate(this.attrs.rotation);
	cx.beginPath();
	cx.moveTo(
		left - this.origin.x,
		top - this.origin.y
	);
	cx.lineTo(
		left - this.origin.x + metrics.width,
		top - this.origin.y
	);
	cx.lineTo(
		left - this.origin.x + metrics.width,
		top - this.origin.y + metrics.height
	);
	cx.lineTo(
		left - this.origin.x,
		top - this.origin.y + metrics.height
	);
	cx.lineTo(
		left - this.origin.x,
		top - this.origin.y
	);
	cx.closePath();
	cx.restore();
};

CanvasText.prototype.draw = function(cx) {
	if (this.isVisible()) {
		cx.font = (this.attrs.fontStyle || "") + " "
				+ (this.attrs.fontWeight || "") + " "
				+ (this.attrs.fontSize ? (this.attrs.fontSize + "px") : "") + " "
				+ (this.attrs.fontFamily || "");
		cx.textAlign = this.attrs.align;
		cx.textBaseline = this.attrs.baseline;
		cx.direction = this.attrs.direction;

		cx.shadowColor = this.attrs.shadowColor;
		cx.shadowBlur = this.attrs.shadowBlur;
		cx.shadowOffsetX = this.attrs.shadowX;
		cx.shadowOffsetY = this.attrs.shadowY;
		cx.globalAlpha = this.attrs.opacity;
		
		cx.save();
		cx.translate(this.attrs.x, this.attrs.y);
		cx.rotate(this.attrs.rotation);
		if (this.attrs.stroke !== null) {
			cx.strokeStyle = this.attrs.stroke;
			cx.strokeText(
				this.textContent,
				-this.origin.x,
				-this.origin.y
			);
		}

		if (this.attrs.fill !== null) {
			cx.fillStyle = this.attrs.fill;
			cx.fillText(
				this.textContent,
				-this.origin.x,
				-this.origin.y
			);
		}
		cx.restore();
	}
};

//stores text
CanvasText.prototype.textContent = null;

//gets/sets text
CanvasText.prototype.val = function(text) {
	if (text === undefined) {
		return this.textContent;
	} else {
		if (typeof text === "string" || typeof text === "number") {
			this.textContent = text;
			
			if (this.span === null) {
				//create span and text
				this.span = document.createElement("span");
				this.spanText = document.createTextNode(text);
				this.spanImg = document.createElement("img");
				
				//the smallest gif - http://probablyprogramming.com/2009/03/15/the-tiniest-gif-ever
				this.spanImg.src = "";
				this.spanImg.alt = "";
				this.spanImg.width = 1;
				this.spanImg.height = 1;
				this.spanImg.style.position = "static";
				this.spanImg.style.display = "inline";
				this.spanImg.style.cssFloat = "none";
				
				this.span.appendChild(this.spanText);
				this.span.appendChild(this.spanImg);
				
				//set styles to hide span and font attributes
				this.span.style.position = "absolute";
				this.span.style.top = "0px";
				this.span.style.left = "0px";
				this.span.style.visibility = "hidden";
				this.span.style.fontFamily = this.attrs.fontFamily;
				this.span.style.fontSize = this.attrs.fontSize + "px";
				this.span.style.fontStyle = this.attrs.fontStyle;
				this.span.style.fontWeight = this.attrs.fontWeight;
				
				//append span to wrapper
				this.sc.wrapper.appendChild(this.span);
			} else {
				this.spanText.nodeValue = text;
			}
			
			this.sc.autorepaint();
		} else {
			throw new TypeError("Passed argument must be string or number.");
		}
		
		return this;
	}
};

//sets font attributes
CanvasText.prototype.setFont = function(value, old, attr) {
	this.span.style[attr] = value + (attr === "fontSize" ? "px" : "");
	this.attrs[attr] = value;
};

//stores HTMLSpan node created for measurement purposes
CanvasText.prototype.span = null;

//stores HTMLSpan text node created for measurement purposes
CanvasText.prototype.spanText = null;

//stores HTMLImg node created for measurement purposes
CanvasText.prototype.spanImg = null;

CanvasText.prototype.metrics = function() {
	var i,
		positions = {
			top: "top",
			middle: "middle",
			bottom: "bottom",
			baseline: "alphabetic"
		},
		result = {
			width: this.span.offsetWidth - 1, //subtract 1 for image
			height: this.span.offsetHeight
		};
	
	for (i in positions) {
		this.spanImg.style.verticalAlign = i;
		result[positions[i]] = this.spanImg.offsetTop;
	}
	
	return result;
};

CanvasText.prototype.box = function() {
	var center, metrics, width, height, alignMove,
		sinRot, sinRot2,
		h1, h2, h3, v1, v2, v3,
		result;
	
	metrics = this.metrics();
	
	if (this.attrs.rotation === 0) {
		//distance from center point to left bound
		alignMove = this.attrs.align === "left" ? 0
			: (this.attrs.align === "right" ? metrics.width : (metrics.width / 2));
		
		return {
			top: Math.round(this.attrs.y - this.origin.y - metrics[this.attrs.baseline]),
			right: Math.round(this.attrs.x - this.origin.x + metrics.width - alignMove),
			bottom: Math.round(this.attrs.y - this.origin.y + metrics.height - metrics[this.attrs.baseline]),
			left: Math.round(this.attrs.x - this.origin.x - alignMove),
			width: metrics.width,
			height: metrics.height
		};
	} else {
		//TODO: calculate it directly
		
		//create rect with text dimensions and position
		var rect = this.sc.rect({
			originX: this.origin.x + (this.attrs.align === "left" ? (-metrics.width / 2) : (this.attrs.align === "right" ? (metrics.width / 2) : 0)),
			originY: this.origin.y + metrics[this.attrs.baseline] - metrics.height / 2,
			x: 150 + this.origin.x,
			y: 150 + this.origin.y,
			width: metrics.width,
			height: metrics.height,
			fill: null,
			visible: false,
			rotation: this.attrs.rotation
		});
		
		result = rect.box();
		
		rect.remove();
		
		return result;
		
//		center = this.rotatedCenter();
//		sinRot = Math.sin(this.attrs.rotation);
//		sinRot2 = Math.sin(Math.PI - this.attrs.rotation);
//		
//		if (this.attrs.align === "center") {
//			v1 = sinRot * metrics.width / 2;
//			v2 = sinRot2 * (metrics.height - metrics[this.attrs.baseline]);
//			v3 = sinRot2 * metrics[this.attrs.baseline];
//			
//			h1 = sinRot2 * metrics.width / 2;
//			h2 = sinRot * (metrics.height - metrics[this.attrs.baseline]);
//			h3 = sinRot * metrics[this.attrs.baseline];
//			
//			return {
//				top: Math.round(center.y - v1 - v3),
//				right: Math.round(center.x + h1 + h3),
//				bottom: Math.round(center.y + v1 + v2),
//				left: Math.round(center.x - h1 - h2),
//				width: 2 * h1 + h2 + h3,
//				height: 2 * v1 + v2 + v3
//			};
//		} else if (this.attrs.align === "left") {
//			v1 = sinRot * metrics.width;
//			v2 = sinRot2 * (metrics.height - metrics[this.attrs.baseline]);
//			v3 = sinRot2 * metrics[this.attrs.baseline];
//			
//			h1 = sinRot2 * metrics.width;
//			h2 = sinRot * (metrics.height - metrics[this.attrs.baseline]);
//			h3 = sinRot * metrics[this.attrs.baseline];
//			
//			return {
//				top: Math.round(center.y - v3),
//				right: Math.round(center.x + h1 + h3),
//				bottom: Math.round(center.y + v1 + v2),
//				left: Math.round(center.x - h2),
//				width: h1 + h2 + h3,
//				height: v1 + v2 + v3
//			};
//		} else if (this.attrs.align === "right") {
//			v1 = sinRot * metrics.width;
//			v2 = sinRot2 * (metrics.height - metrics[this.attrs.baseline]);
//			v3 = sinRot2 * metrics[this.attrs.baseline];
//			
//			h1 = sinRot2 * metrics.width;
//			h2 = sinRot * (metrics.height - metrics[this.attrs.baseline]);
//			h3 = sinRot * metrics[this.attrs.baseline];
//			
//			return {
//				top: Math.round(center.y - v1 - v3),
//				right: Math.round(center.x + h3),
//				bottom: Math.round(center.y + v2),
//				left: Math.round(center.x - h1 - h2),
//				width: h1 + h2 + h3,
//				height: v1 + v2 + v3
//			};
//		}
	}
};